<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>Chat Stream 测试</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif; margin: 24px; }
    .row { display: flex; gap: 8px; margin-bottom: 12px; }
    input[type="text"] { flex: 1; padding: 8px; font-size: 14px; }
    button { padding: 8px 12px; font-size: 14px; cursor: pointer; }
    #status { margin-left: 6px; color: #666; }
    #output {
      width: 100%; height: 360px; padding: 12px; border: 1px solid #ddd; border-radius: 6px;
      background: #fafafa; overflow: auto; white-space: pre-wrap; line-height: 1.6;
    }
  </style>
</head>
<body>
  <h2>Chat Stream 接口测试</h2>

  <div class="row">
    <input id="prompt" type="text" placeholder="输入提示词，例如：用100字介绍流式输出的好处" />
    <button id="start">开始流式</button>
    <button id="stop" disabled>停止</button>
    <span id="status"></span>
  </div>

  <div id="output" aria-label="stream-output"></div>

  <script>
    let abortController = null;

    const promptEl = document.getElementById('prompt');
    const startBtn = document.getElementById('start');
    const stopBtn = document.getElementById('stop');
    const statusEl = document.getElementById('status');
    const outputEl = document.getElementById('output');

    startBtn.addEventListener('click', startStream);
    stopBtn.addEventListener('click', stopStream);
    promptEl.addEventListener('keydown', e => {
      if (e.key === 'Enter') startStream();
    });

    async function startStream() {
      const prompt = (promptEl.value || '').trim();
      if (!prompt) {
        alert('请输入提示词');
        promptEl.focus();
        return;
      }

      outputEl.textContent = '';
      statusEl.textContent = '连接中...';
      startBtn.disabled = true;
      stopBtn.disabled = false;

      const url = `${window.location.origin}/chat_stream?prompt=${encodeURIComponent(prompt)}`;
      abortController = new AbortController();

      try {
        const resp = await fetch(url, {
          method: 'GET',
          headers: { 'Accept': 'text/plain' },
          cache: 'no-store',
          signal: abortController.signal
        });

        if (!resp.ok) {
          statusEl.textContent = `错误：${resp.status}`;
          startBtn.disabled = false;
          stopBtn.disabled = true;
          return;
        }

        statusEl.textContent = '流式输出中...';
        const reader = resp.body.getReader();
        const decoder = new TextDecoder('utf-8');

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          const chunk = decoder.decode(value, { stream: true });
          outputEl.textContent += chunk;
          outputEl.scrollTop = outputEl.scrollHeight;
        }

        statusEl.textContent = '完成';
      } catch (err) {
        if (err.name === 'AbortError') {
          statusEl.textContent = '已停止';
        } else {
          statusEl.textContent = `异常：${err.message || err}`;
        }
      } finally {
        startBtn.disabled = false;
        stopBtn.disabled = true;
        abortController = null;
      }
    }

    function stopStream() {
      if (abortController) {
        abortController.abort();
      }
    }
  </script>
</body>
</html>